package coll

import (
	"errors"
	"gitee.com/hongzhaomin/hzm-common-go/assert"
	"gitee.com/hongzhaomin/hzm-common-go/streams"
)

type Set[E comparable] map[E]struct{}

// NewSet 创建一个set集合
func NewSet[E comparable]() *Set[E] {
	return NewSetWithCap[E](0)
}

// NewSetWithCap 创建一个set集合, 可设置 cap容量
func NewSetWithCap[E comparable](cap int) *Set[E] {
	set := make(map[E]struct{}, cap)
	return (*Set[E])(&set)
}

func OfSet[E comparable](keyMap map[E]struct{}) *Set[E] {
	newSet := NewSetWithCap[E](len(keyMap))
	for e := range keyMap {
		newSet.Add(e)
	}
	return newSet
}

func NewSet4Slice[E comparable](slice []E) *Set[E] {
	set := NewSetWithCap[E](len(slice))
	for _, ele := range slice {
		set.Add(ele)
	}
	return set
}

func (my *Set[E]) ToList() *List[E] {
	list := make([]E, 0, my.Size())
	for key := range *my {
		list = append(list, key)
	}
	return OfList(list)
}

// Stream 将Set转化为Stream流处理
func (my *Set[E]) Stream() streams.Stream[E] {
	return streams.OfSlice(*my.ToList())
}

// ForEach 切片的循环操作
func (my *Set[E]) ForEach(action func(t E)) {
	assert.NonNil(action, "action func must not nil")
	for e := range *my {
		action(e)
	}
}

func (my *Set[E]) Add(ele E) {
	if !my.isValid(ele) {
		panic(errors.New("无效元素"))
	}
	(*my)[ele] = struct{}{}
}

func (my *Set[E]) Remove(ele E) bool {
	if !my.Contains(ele) {
		return false
	}
	delete(*my, ele)
	return true
}

func (my *Set[E]) Size() int {
	return len(*my)
}

func (my *Set[E]) Contains(ele E) bool {
	if !my.isValid(ele) {
		return false
	}
	_, ok := (*my)[ele]
	return ok
}

func (my *Set[E]) IsEmpty() bool {
	return *my == nil || my.Size() == 0
}

func (my *Set[E]) isValid(ele E) bool {
	return isValid(ele)
}
